import React, { useEffect, useState } from 'react';
import { Select, Spin } from 'antd';
import { defaultFormatResult } from '@/hooks';
import { fetchDutyList } from '@/services/components/userform';
import { isObject, size, isFunction } from 'lodash';
import styles from './index.less';

const { Option } = Select;

/**
 * 缓存数据
 * @type {{add(*, *): void, data: {}, get(*): *, clear(*): void, clearAll(): void}}
 */
const CACHE = {
    data: {},
    get(key) {
        return CACHE.data[key];
    },
    add(key, value) {
        CACHE.data[key] = value;
    },
    clear(key) {
        delete CACHE.data[key];
    },
    clearAll() {
        CACHE.data = {};
    }
};

/**
 * 正在加载请求的缓存
 * @type {{add(*, *): void, data: {}, get(*): *, remove(*): void}}
 */
const loadingCache = {
    data: {},
    get(key) {
        return loadingCache.data[key];
    },
    add(key, promise) {
        loadingCache.data[key] = promise;
    },
    remove(key) {
        delete loadingCache.data[key];
    }
};

/**
 *
 * @description 岗位下拉选择
 * @param {Boolean} isFullName 是否显示levelName  默认不显示
 * @param {String}  mode 设置 Select 模式 multiple | tags为多选或标签，默认单选
 * @param {String} labelInValue 返回数组对象
 * @param {Array | function} dataSource 数据源
 * @param {String} [cacheKey] 缓存key,当页面中当时有好几个地方使用同步请求时，可以启用缓存，要清除时可以调用clearCache
 *
 */
const DutySelect = React.forwardRef(
    (
        {
            value,
            onChange,
            mode = false,
            isFullName = false,
            labelInValue = false,
            dataSource,
            cacheKey = null,
            ...rest
        },
        ref
    ) => {
        const [loading, setLoading] = useState(false);
        const [data, setData] = useState(null);

        useEffect(() => {
            let requestPromise;

            if (cacheKey && CACHE.get(cacheKey)) {
                // 存在缓存时
                requestPromise = CACHE.get(cacheKey);
            } else if (cacheKey && loadingCache.get(cacheKey)) {
                // 正在加载时
                requestPromise = loadingCache.get(cacheKey);
            } else if (dataSource) {
                // 有数据时
                requestPromise = isFunction(dataSource) ? dataSource() : dataSource;
            } else {
                requestPromise = fetchDutyList();
            }

            if (cacheKey && !loadingCache.get(cacheKey)) {
                loadingCache.add(cacheKey, requestPromise);
            }

            setLoading(true);
            Promise.all([requestPromise])
                .then(([res]) =>
                    res.hasOwnProperty('code') && res.hasOwnProperty('msg')
                        ? defaultFormatResult.formatResult(res)
                        : res
                )
                .then(response => {
                    setData(response);
                    if (cacheKey) {
                        // 从待加载缓存中移除
                        loadingCache.remove(cacheKey);
                        // 添加到缓存
                        CACHE.add(cacheKey, response);
                    }
                })
                .finally(() => setLoading(false));
        }, []);

        const [selectValue, setSelectValue] = useState();

        useEffect(() => {
            let tempValue = value;
            if (size(value) > 0) {
                if (labelInValue && Array.isArray(value)) {
                    tempValue = value.map(item => {
                        if (isObject(item)) {
                            return item;
                        }
                        return {
                            label: '',
                            key: item
                        };
                    });
                }
            }
            setSelectValue(size(tempValue) > 0 ? tempValue : undefined);
        }, [value, labelInValue]);
        const handleChange = changeValue => {
            if (onChange) {
                onChange(changeValue);
            }
        };

        return (
            <Spin spinning={loading} wrapperClassName={styles.selectSpingWrapper}>
                <Select
                    ref={ref}
                    showSearch
                    allowClear
                    mode={mode}
                    placeholder="请选择岗位"
                    labelInValue={labelInValue}
                    value={selectValue}
                    onChange={handleChange}
                    optionFilterProp="children"
                    optionLabelProp="label"
                    style={{ minWidth: '180px' }}
                    dropdownStyle={{
                        maxHeight: 350,
                        overflow: 'auto'
                    }}
                    getPopupContainer={triggerNode => triggerNode.parentElement}
                    filterOption={(inputValue, option) => {
                        const matchStr = isFullName ? option.props?.title : option.props?.label;
                        return !inputValue || matchStr.toLowerCase().includes(inputValue.toLowerCase())
                    }}
                    {...rest}
                >
                    {data &&
                        data?.map(item => {
                            const { levelName, dutyCode, dutyAlias, deleteFlag } = item;
                            return (
                                <Option
                                    value={dutyCode}
                                    key={dutyCode}
                                    label={dutyAlias}
                                    title={`${levelName} - ${dutyAlias}`}
                                >
                                    {isFullName === true
                                        ?
                                            <>
                                                <span style={{ color: '#ffa22d' }}>{levelName}</span> - {dutyAlias}
                                                <span style={{ color: 'red' }}>{deleteFlag === 1 ? '（已删除）' : ''}</span>
                                            </>
                                        : <>
                                            {dutyAlias}
                                            <span style={{ color: 'red' }}>{deleteFlag === 1 ? '（已删除）' : ''}</span>
                                        </>
                                    }
                                </Option>
                            );
                        })}
                </Select>
            </Spin>
        );
    }
);

export default DutySelect;

const { clear, clearAll } = CACHE;
export { clear as clearCache, clearAll as clearAllCache };
